package fr.umlv.ig.extraWindows;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

import fr.umlv.ig.model.MetroModelImpl;
import fr.umlv.ig.model.Station;

/**
 * Represents the frame to configure a station.
 * @author jenseric
 * @Author william
 *
 */
@SuppressWarnings("serial")
public class StationWindow extends ExtraWindow {
	/**The model where is the station*/
	private final MetroModelImpl metroModel;
	
	/**The station concerned by the configuration*/
	private Station station;
	
	/**Text for the status*/
	private String status =  "Status : ";
	
	/**Text for the waiting time of the station*/
	private String waitingTime = "Waiting time : ";
	
	/**Map which associate each next station of the statoin by a {@link JSpinner}*/
	private final Map<Station, JSpinner> mapStationSpinner;
	
	/**Panel used by this frame configuration*/
	private JPanel p = new JPanel(new GridBagLayout());
	
	/**Label used for the text of the status*/
	private final JLabel labelStatus = new JLabel(status);
	

	/**Label used for the text of the waiting time*/
	private final JLabel labelWaitingTime = new JLabel(waitingTime);

	
	/**
	 * Initializes a {@link StationWindow}.
	 * @param owner the frame which launch the frame.
	 * @param title the title of the frame.
	 * @param model the model concerned by the configuration.
	 * @param station the station concerned by the configuration at the first time.
	 */
	public StationWindow(JFrame owner, String title,MetroModelImpl model, Station station) {
		super(owner, title, true, 380, 300);
		mapStationSpinner = new HashMap<Station, JSpinner>(3);
		this.metroModel = model;
		this.station = station;
		p.setPreferredSize(new Dimension(350, 290));
		init();
		dispose();
		
	}

	/**
	 * Initializes the components of the frame.
	 */
	private void init() {


		p.setBorder(BorderFactory.createTitledBorder("Configuration of " + station.getName()));

		GridBagConstraints gbc = new GridBagConstraints();

		/************status of the station*******************************/
		gbc.gridwidth=2;
		gbc.fill=GridBagConstraints.HORIZONTAL;
		gbc.weightx=1f;
		gbc.weighty=1f;
		p.add(labelStatus, gbc);

		final ButtonGroup group=new ButtonGroup();
		JRadioButton radioButtonTrue = new JRadioButton("Open");
		JRadioButton radioButtonFalse = new JRadioButton("Close");

		gbc.gridwidth=2;
		gbc.fill=GridBagConstraints.HORIZONTAL;
		gbc.weightx=1f;
		gbc.weighty=1f;
		p.add(radioButtonTrue, gbc);

		gbc.gridwidth=GridBagConstraints.REMAINDER;
		gbc.fill=GridBagConstraints.HORIZONTAL;
		gbc.weightx=1f;
		gbc.weighty=1f;
		p.add(radioButtonFalse, gbc);

		group.add(radioButtonTrue);
		group.add(radioButtonFalse);
		if(metroModel.isOpened(station)) {
			group.setSelected(radioButtonTrue.getModel(), true);
		}
		else {
			group.setSelected(radioButtonFalse.getModel(), true);
		}
		/*******************************************************************/

		/****************waiting time of the station ***********************/
		gbc.gridwidth=2;
		gbc.fill=GridBagConstraints.HORIZONTAL;
		gbc.weightx=1f;
		gbc.weighty=1f;
		p.add(labelWaitingTime, gbc);

		gbc.gridwidth=GridBagConstraints.REMAINDER;
		gbc.fill=GridBagConstraints.NONE;
		gbc.weightx=1f;
		gbc.weighty=1f;
		final SpinnerNumberModel spinnerWaitingTimeModel = new SpinnerNumberModel(metroModel.getWaitingTime(station), 0, 999, 1);
		final JSpinner spinner = new JSpinner(spinnerWaitingTimeModel);
		spinner.setPreferredSize(new Dimension(40,20));
		p.add(spinner, gbc);


		/********************************************************************/

		/****************nextWaiting times of the station ***********************/
		gbc.gridwidth=2;
		gbc.fill=GridBagConstraints.HORIZONTAL;
		gbc.weightx=1f;
		gbc.weighty=1f;

		final Map<Station,Station> mapNextStations = metroModel.getMapNextStations(station);
		for(Entry<Station, Station> entryStation : mapNextStations.entrySet()) {
			Station nextStation = entryStation.getValue();
			StringBuilder nextStationBuilder = new StringBuilder();
			nextStationBuilder.append(station.getName());
			nextStationBuilder.append(" -> ");
			nextStationBuilder.append(nextStation.getName());
			nextStationBuilder.append(" : ");

			gbc.gridwidth=2;
			gbc.fill=GridBagConstraints.HORIZONTAL;
			gbc.weightx=1f;
			gbc.weighty=1f;
			JLabel waitingNextStation = new JLabel(nextStationBuilder.toString());
			p.add(waitingNextStation, gbc);

			int nextStationTime = metroModel.getWaitingTime(station, nextStation);
			final SpinnerNumberModel spinnerWaitingNextModel = new SpinnerNumberModel(nextStationTime, 0, 999, 1);

			gbc.gridwidth=GridBagConstraints.REMAINDER;
			gbc.fill=GridBagConstraints.NONE;
			gbc.weightx=1f;
			gbc.weighty=1f;
			final JSpinner spinnerWaitingNext = new JSpinner(spinnerWaitingNextModel);
			spinnerWaitingNext.setPreferredSize(new Dimension(40,20));
			p.add(spinnerWaitingNext, gbc);
			mapStationSpinner.put(nextStation, spinnerWaitingNext);
		}

		gbc.gridwidth=2;
		gbc.fill=GridBagConstraints.NONE;
		gbc.weightx=1f;
		gbc.weighty=1f;
		JButton buttonOk = new JButton("OK");
		buttonOk.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					spinner.commitEdit();
					int time = (Integer) spinnerWaitingTimeModel.getValue();
					metroModel.setWaitingTime(station, time);

					for(Entry<Station, Station> entryStation : mapNextStations.entrySet()) {
						Station nextStation = entryStation.getValue();
						JSpinner nextSpinner = mapStationSpinner.get(nextStation);
						nextSpinner.commitEdit();
						int waitingTime = (Integer) nextSpinner.getModel().getValue();
						metroModel.setWaitingTime(station, nextStation, waitingTime);
					}		
				} catch (ParseException e1) {
					e1.printStackTrace();
				}
				
				
				Enumeration<AbstractButton> elements = group.getElements();
				while (elements.hasMoreElements()) {
					AbstractButton button = (AbstractButton)elements.nextElement();
					if (button.isSelected()) {
						if(button.getText().equals("Open")) {
							metroModel.openStation(station);
						}
						else {
							metroModel.closeStation(station);
						}
					}
				}
				dispose();
			}
		});
		p.add(buttonOk, gbc);

		gbc.gridwidth=GridBagConstraints.REMAINDER;
		gbc.fill=GridBagConstraints.NONE;
		gbc.weightx=1f;
		gbc.weighty=1f;
		JButton buttonCancel = new JButton("Cancel");
		buttonCancel.addActionListener(dialogListner);
		p.add(buttonCancel, gbc);

		add(p);
	}



	@Override
	public void start() {
		setLocationRelativeTo(getOwner());
		setVisible(true);
	}

	/**
	 * Calls when the frame is opened before a nex configuration for a new
	 * station. 
	 * @param currentStation the currentStation of the configuration frame.
	 */
	public void reload(Station currentStation) {
		station = currentStation;
		mapStationSpinner.clear();
		p.removeAll();
		init();
		dispose();
	}

}
